<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    body {
      padding: 20px;
    }
    div, li, p {
      line-height: 40px;
    }
    span {
      color: red;
    }
  </style>
</head>
<body>
  <h2>Iterator</h2>
  <ul>
    <li>
      Javascript原有的表示集合二点数据结构主要是数组(Array)和对象(Object),ES6又提供了添加了Map和Set.需要一种统一的接口机制来处理所有的不同的数据结构
    </li>
    <li>遍历器就是这么一种机制.它是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构,<span>只要部署Iterator接口,就可以完成遍历操作</span>(即依次处理该数据结构的所有成员)</li>
    <li>
      <h3>Iterator的作用</h3>
      <ul>
        <li>1.为各种数据结构提供一个统一,简便的访问接口</li>
        <li>2.使得数据结构的成员能够按某种次序排列</li>
        <li>3.ES6创造了一种新的遍历命令--for...of循环,Iterator接口主要供for...of消费</li>
      </ul>
    </li>
    <li>
      <h3>Iterator的遍历过程</h3>
      <ul>
        <li>
          1.创建一个对象,指向当前数据结构的起始位置.也就是说,<span>遍历器对象本质上就是一个指针对象</span>
        </li>
        <li>
          2.第一次调用指针对象的next()方法,可以将指针指向数据结构的第一个成员
        </li>
        <li>3.第二次调用,指针指向数据结构的第二个成员</li>
        <li>4.不断调用,直到它指向数据结构的结束位置</li>
      </ul>
    </li>
    <li>
      每次调用next(),都会返回数据结构的当前成员的信息.具体来说,就是返回一个包含value和done两个属性的对象.其中value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束
    </li>
  </ul>

  <h2>默认Iterator接口</h2>
  <ul>
    <li>
      Iterator接口的目的是为所有数据结构提供一种统一的访问机制,即for...of循环.当使用for...of循环遍历某种数据结构时,该循环会自动寻找Iterator接口
    </li>
    <li>
      数据结构只要部署了Iterator接口,我们就称这种数据结构为""可遍历的"
    </li>
    <li>
      ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性.或者说,<span>一个数据结构只要具有Symbol.iterator属性,就可以认为是可遍历的.调用Symbol.iterator方法,我们会得到当前数据的结构默认的遍历器生成函数.</span>该对象的根本特征就是具有next方法
    </li>
    <li>
      <h3>原生具备Iterator接口的数据结构如下</h3>
      <ul>
        <li>Array</li>
        <li>Map</li>
        <li>Set</li>
        <li>String</li>
        <li>TypedArray</li>
        <li>函数的arguments对象</li>
        <li>NodeList对象</li>
      </ul>
      <div>
        Ⅰ.对于原生部署Iterator接口的数据结构,我们不用自己编写遍历器生成函数,for...of循环会自动遍历他们.除此之外,其他数据结构(主要是对象)的Iterator接口都需要自己在Symbol.iterator属性上部署,这样才会被for...of循环遍历
      </div>
      <div>
        Ⅱ.一个对象如果要具备可被for...of循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可以)
      </div>
    </li>
    <li>
      普通对象部署数组的Symbol.iterator方法并无效果
    </li>
    <li>
      如果Symbol.iterator方法对应的不是遍历器生成函数,解释引擎将会报错
    </li>
    <li>
      有了遍历器接口,数据结构就可以使用for ... of 循环遍历,也可以使用while循环遍历
    </li>
  </ul>

  <h2>调用Iterator接口的场合</h2>
  <ul>
    <li>对数组和Set进行解构赋值时,会默认调用Symbol.iterator方法</li>
    <li>
      扩展运算符(...)也会调用默认的Iterator接口.只要某个数据解构部署了Iterator接口,就可以对它使用扩展运算符,将其转为数组
    </li>
    <li>任何接受数组作为参数的场合其实都调用了遍历器接口.</li>
  </ul>


  <h2>其他方法</h2>
  <ul>
    <li>
      字符串是一个类似数组的对象,也具有原生Iterator接口.可以覆盖原生的Symbol.iterator方法达到修改遍历器行为的目的
    </li>
    <li>
      遍历器对象除了具有next方法,还可以具有return 方法和throw方法.如果自己写遍历器对象生成函数,那么next方法是必须部署的.return 方法和throw方法则是可选部署的
    </li>
    <li>
      return 方法使用场合是,如果for...of...循环提前退出(通常是因为出错,或者有break语句或continue语句),就会调用return方法;如果一个元素再完成遍历前需要清理或释放资源,就可以部署return方法
    </li>
    <li>
      throw参阅17章
    </li>
  </ul>
</body>
</html>